package com.intelligent.system.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.intelligent.system.common.dto.MessageDTO;
import com.intelligent.system.common.dto.MessageQueryDTO;
import com.intelligent.system.common.entity.Message;
import com.intelligent.system.common.exception.CustomException;
import com.intelligent.system.common.manager.SseEmitterManager;
import com.intelligent.system.common.mapper.MessageMapper;
import com.intelligent.system.common.response.ResultDO;
import com.intelligent.system.common.service.IMessageService;
import com.intelligent.system.common.utils.SnowflakeIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements IMessageService {

    @Resource
    private SnowflakeIdUtils idUtils;
    
    @Resource
    private SseEmitterManager sseEmitterManager;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> sendMessage(MessageDTO messageDTO) {
        try {
            // 参数校验
            if (Objects.isNull(messageDTO)) {
                return ResultDO.error(400, "消息信息不能为空");
            }
            if (StringUtils.isBlank(messageDTO.getTitle())) {
                return ResultDO.error(400, "消息标题不能为空");
            }
            if (StringUtils.isBlank(messageDTO.getContent())) {
                return ResultDO.error(400, "消息内容不能为空");
            }
            if (Objects.isNull(messageDTO.getReceiverId())) {
                return ResultDO.error(400, "接收者ID不能为空");
            }

            // 构建消息实体
            Message message = new Message();
            BeanUtils.copyProperties(messageDTO, message);
            message.setId(idUtils.nextId());
            message.setTimestamp(System.currentTimeMillis());
            message.setStatus(0); // 设置初始状态为未读
            message.setIsBroadcast(0); // 设置为非广播消息

            // 保存消息
            if (!this.save(message)) {
                return ResultDO.error(500, "发送消息失败");
            }

            // 通过SSE推送消息
            if (sseEmitterManager.isUserOnline(messageDTO.getReceiverId())) {
                sseEmitterManager.sendMessage(messageDTO.getReceiverId(), messageDTO);
            }

            log.info("消息发送成功，消息ID：{}", message.getId());
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("发送消息失败", e);
            throw new CustomException("发送消息失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> sendBroadcast(MessageDTO messageDTO) {
        try {
            // 参数校验
            if (Objects.isNull(messageDTO)) {
                return ResultDO.error(400, "广播消息信息不能为空");
            }
            if (StringUtils.isBlank(messageDTO.getTitle())) {
                return ResultDO.error(400, "广播消息标题不能为空");
            }
            if (StringUtils.isBlank(messageDTO.getContent())) {
                return ResultDO.error(400, "广播消息内容不能为空");
            }
            if (Objects.isNull(messageDTO.getBroadcastScope())) {
                return ResultDO.error(400, "广播范围不能为空");
            }

            // 构建广播消息实体
            Message message = new Message();
            BeanUtils.copyProperties(messageDTO, message);
            message.setId(idUtils.nextId());
            message.setTimestamp(System.currentTimeMillis());
            message.setStatus(0); // 设置初始状态为未读
            message.setIsBroadcast(1); // 设置为广播消息
            message.setReceiverId(null); // 广播消息不需要指定接收者

            // 保存广播消息
            if (!this.save(message)) {
                return ResultDO.error(500, "发送广播消息失败");
            }

            // 通过SSE推送广播消息
            int successCount = sseEmitterManager.broadcastMessage(messageDTO);
            log.info("广播消息推送完成，成功推送用户数：{}", successCount);

            log.info("广播消息发送成功，消息ID：{}", message.getId());
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("发送广播消息失败", e);
            throw new CustomException("发送广播消息失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<MessageDTO> getMessage(Long id) {
        try {
            Message message = this.getById(id);
            if (message == null) {
                return ResultDO.error(404, "消息不存在");
            }

            MessageDTO messageDTO = new MessageDTO();
            BeanUtils.copyProperties(message, messageDTO);
            return ResultDO.success(messageDTO);
        } catch (Exception e) {
            log.error("获取消息详情失败", e);
            throw new CustomException("获取消息详情失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> updateStatus(Long id, Integer status) {
        try {
            Message message = this.getById(id);
            if (message == null) {
                return ResultDO.error(404, "消息不存在");
            }

            message.setStatus(status);
            if (!this.updateById(message)) {
                return ResultDO.error(500, "更新消息状态失败");
            }

            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("更新消息状态失败", e);
            throw new CustomException("更新消息状态失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> deleteMessage(Long id) {
        try {
            if (!this.removeById(id)) {
                return ResultDO.error(500, "删除消息失败");
            }
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("删除消息失败", e);
            throw new CustomException("删除消息失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<IPage<MessageDTO>> pageMessages(Page<MessageDTO> page, MessageQueryDTO queryDTO) {
        try {
            // 构建查询条件
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StringUtils.isNotBlank(queryDTO.getType()), Message::getType, queryDTO.getType())
                    .eq(queryDTO.getStatus() != null, Message::getStatus, queryDTO.getStatus())
                    .eq(queryDTO.getLevel() != null, Message::getLevel, queryDTO.getLevel())
                    .eq(queryDTO.getIsBroadcast() != null, Message::getIsBroadcast, queryDTO.getIsBroadcast())
                    .eq(queryDTO.getBroadcastScope() != null, Message::getBroadcastScope, queryDTO.getBroadcastScope())
                    .and(StringUtils.isNotBlank(queryDTO.getKeyword()), w -> w
                            .like(Message::getTitle, queryDTO.getKeyword())
                            .or()
                            .like(Message::getContent, queryDTO.getKeyword()))
                    .orderByDesc(Message::getCreateTime);

            // 执行分页查询
            Page<Message> messagePage = new Page<>(page.getCurrent(), page.getSize());
            IPage<Message> resultPage = this.page(messagePage, wrapper);

            // 转换为DTO
            IPage<MessageDTO> dtoPage = resultPage.convert(message -> {
                MessageDTO dto = new MessageDTO();
                BeanUtils.copyProperties(message, dto);
                return dto;
            });

            return ResultDO.success(dtoPage);
        } catch (Exception e) {
            log.error("分页查询消息列表失败", e);
            throw new CustomException("分页查询消息列表失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<Long> getUnreadCount(Long receiverId) {
        try {
            // 查询未读消息数量
            Long count = this.count(new LambdaQueryWrapper<Message>()
                    .eq(Message::getReceiverId, receiverId)
                    .eq(Message::getStatus, 0));
            return ResultDO.success(count);
        } catch (Exception e) {
            log.error("获取未读消息数量失败", e);
            throw new CustomException("获取未读消息数量失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<List<MessageDTO>> getUserMessages(Long receiverId, MessageQueryDTO queryDTO) {
        try {
            // 构建查询条件
            LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Message::getReceiverId, receiverId)
                    .or()
                    .eq(Message::getIsBroadcast, 1)
                    .eq(StringUtils.isNotBlank(queryDTO.getType()), Message::getType, queryDTO.getType())
                    .eq(queryDTO.getStatus() != null, Message::getStatus, queryDTO.getStatus())
                    .eq(queryDTO.getLevel() != null, Message::getLevel, queryDTO.getLevel())
                    .orderByDesc(Message::getCreateTime);

            // 执行查询
            List<Message> messages = this.list(wrapper);

            // 转换为DTO
            List<MessageDTO> messageDTOs = messages.stream().map(message -> {
                MessageDTO dto = new MessageDTO();
                BeanUtils.copyProperties(message, dto);
                return dto;
            }).collect(Collectors.toList());

            return ResultDO.success(messageDTOs);
        } catch (Exception e) {
            log.error("获取用户消息列表失败", e);
            throw new CustomException("获取用户消息列表失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> batchUpdateStatus(List<Long> ids, Integer status) {
        try {
            // 批量更新消息状态
            List<Message> messages = ids.stream().map(id -> {
                Message message = new Message();
                message.setId(id);
                message.setStatus(status);
                return message;
            }).collect(Collectors.toList());

            if (!this.updateBatchById(messages)) {
                return ResultDO.error(500, "批量更新消息状态失败");
            }

            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("批量更新消息状态失败", e);
            throw new CustomException("批量更新消息状态失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> batchDelete(List<Long> ids) {
        try {
            if (!this.removeByIds(ids)) {
                return ResultDO.error(500, "批量删除消息失败");
            }
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("批量删除消息失败", e);
            throw new CustomException("批量删除消息失败：" + e.getMessage(), 500);
        }
    }
} 